﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.Exceptions;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using YArchitech.Controls;
using YArchitech.LIB;
using YArchitech.Revit;

namespace HYFloorPipeModule
{
	public class RectFloorPipe
	{
		public RectFloorPipe(UIApplication uiApp, Selection sel)
		{
			this.floorPipeTools = new FloorPipeTools(uiApp);
			this.uiDocument = uiApp.ActiveUIDocument;
			this.document = uiApp.ActiveUIDocument.Document;
			this.selection = sel;
		}

		public RectFloorPipe(UIApplication uiApp, Selection sel, Dictionary<string, string> dicPara, Room rom = null)
		{
			this.floorPipeTools = new FloorPipeTools(uiApp);
			this.uiDocument = uiApp.ActiveUIDocument;
			this.document = uiApp.ActiveUIDocument.Document;
			this.selection = sel;
			this.dic = dicPara;
			this.room = rom;
			this.bLayOnce = true;
		}

		public void StartDraw()
		{
			List<GraphicsStyle> lineStyle = this.floorPipeTools.GetLineStyle();
			HYDrawDrpgForm df = new HYDrawDrpgForm(lineStyle, this.dic);
			if (df.ShowDialog() == DialogResult.OK)
			{
				SubTransaction subTransaction = new SubTransaction(this.document);
				for (;;)
				{
					try
					{
						if (df.bLayInRoom)
						{
							Document docment = null;
							Reference reference = this.floorPipeTools.PickUpRoomOrSpace(ref this.room, this.document, this.selection, ref docment, df.BeLinkSelect);
							if (reference == null && this.room == null)
							{
								YJKMessageBox.Information("请选择矩形房间或空间！");
								this.room = null;
								continue;
							}
							List<List<XYZ>> list = this.floorPipeTools.GetRoomInfoXyzs(this.room, reference, this.selection, 1, docment);
							if (list == null)
							{
								YJKMessageBox.Information("请选择矩形房间或空间！");
								this.room = null;
								continue;
							}
							subTransaction.Start();
							int nNum = 0;
							list.ForEach(delegate(List<XYZ> ps)
							{
								nNum = this.DrawMore(ps, df.drawFloorPipeData);
							});
							if (nNum > 1)
							{
								list = this.floorPipeTools.SplitRectangl(list[0], nNum);
							}
							foreach (List<XYZ> point in list)
							{
								this.DrawPipes(point, df.drawFloorPipeData, df.bMarkTag);
							}
							this.room = null;
						}
						else
						{
							XYZ xyz = this.selection.PickPoint("请选择矩形区域第一点：");
							XYZ xyz2 = null;
							XYZ pt = null;
							using (PipeCreateJigPolarAxis pipeCreateJigPolarAxis = new PipeCreateJigPolarAxis(this.uiDocument))
							{
								pipeCreateJigPolarAxis.StartPoint = xyz;
								Application.DoEvents();
								xyz2 = pipeCreateJigPolarAxis.PickEndPoint(xyz, "请选择矩形区域第二点：");
								pipeCreateJigPolarAxis.StartPoint = xyz2;
								Application.DoEvents();
								pt = pipeCreateJigPolarAxis.PickEndPoint(xyz2, "请选择矩形区域第三点：");
								pipeCreateJigPolarAxis.Dispose();
							}
							subTransaction.Start();
							List<XYZ> list2 = this.floorPipeTools.DealRectPoints(xyz, xyz2, pt, this.selection);
							this.DrawPipes(list2[1], list2[2], list2[3], df.drawFloorPipeData, df.bMarkTag);
						}
						subTransaction.Commit();
						if (!this.bLayOnce)
						{
							continue;
						}
					}
					catch (Autodesk.Revit.Exceptions.OperationCanceledException)
					{
						if (subTransaction != null && (int)subTransaction.GetStatus() == 1)
						{
							subTransaction.Commit();
						}
					}
					catch (Exception ex)
					{
						ex.ToString();
						YJKMessageBox.Information("绘制出错，请检查绘制数据！\n");
						if (subTransaction != null && (int)subTransaction.GetStatus() == 1)
						{
							subTransaction.RollBack();
						}
						this.room = null;
						continue;
					}
					break;
				}
			}
		}

		public void StartDrawYX()
		{
			HYDrawYXDrpgForm hydrawYXDrpgForm = new HYDrawYXDrpgForm(this.floorPipeTools.GetLineStyle(), this.dic);
			if (hydrawYXDrpgForm.ShowDialog() == DialogResult.OK)
			{
				for (;;)
				{
					SubTransaction subTransaction = new SubTransaction(this.document);
					try
					{
						FloorPipeGroupData floorPipeGroupData = new FloorPipeGroupData();
						floorPipeGroupData.drawYxFloorPipeData = hydrawYXDrpgForm.drawYxFloorPipe;
						XYZ markPoint = null;
						YXFloorPipeManager yxfloorPipeManager;
						if (hydrawYXDrpgForm.bLayInRoom)
						{
							Element element = null;
							Document linkdocment = null;
							Reference reference = this.floorPipeTools.PickUpRoomOrSpace(ref element, this.document, this.selection, ref linkdocment, hydrawYXDrpgForm.BeLinkSelect);
							if (reference == null && element == null)
							{
								YJKMessageBox.Information("请选择绘制盘管需要的房间或空间！");
								element = null;
								continue;
							}
							List<MixPair> roomBoundingInfo = this.floorPipeTools.GetRoomBoundingInfo(element, this.selection, reference, linkdocment);
							if (element.Document.IsLinked)
							{
								LinkedDocument linkedDocument = this.document.GetLinkedDocument(element.Id);
								for (int i = 0; i < roomBoundingInfo.Count; i++)
								{
									if (roomBoundingInfo[i] != null)
									{
										roomBoundingInfo[i].Start = linkedDocument.GetPointInLinkDocument(roomBoundingInfo[i].Start);
										roomBoundingInfo[i].End = linkedDocument.GetPointInLinkDocument(roomBoundingInfo[i].End);
									}
								}
							}
							yxfloorPipeManager = new YXFloorPipeManager(roomBoundingInfo, hydrawYXDrpgForm.drawYxFloorPipe);
							markPoint = YJKRevitTools.Centroid(element);
						}
						else
						{
							List<XYZ> list = new List<XYZ>();
							try
							{
								XYZ xyz = this.selection.PickPoint("请按顺序选取异形地热盘管布置区域的顶点（按ESC退出选点）：");
								using (PipeCreateJigPolarAxis pipeCreateJigPolarAxis = new PipeCreateJigPolarAxis(this.uiDocument))
								{
									for (;;)
									{
										if (pipeCreateJigPolarAxis.StartPoint == null)
										{
											if (list.Count == 0 || (xyz.DistanceTo(list.Last<XYZ>()) > 0.0001 && !this.JustSetContantXyz(list, xyz)))
											{
												list.Add(xyz);
											}
											pipeCreateJigPolarAxis.StartPoint = xyz;
											Application.DoEvents();
										}
										else
										{
											Application.DoEvents();
											XYZ xyz2 = pipeCreateJigPolarAxis.PickEndPoint(list[list.Count - 1], "请选择下一个顶点：");
											if (xyz2 == null)
											{
												break;
											}
											if (list.Count == 0 || (xyz2.DistanceTo(list.Last<XYZ>()) > 0.0001 && !this.JustSetContantXyz(list, xyz2)))
											{
												list.Add(xyz2);
											}
										}
									}
								}
							}
							catch (Autodesk.Revit.Exceptions.OperationCanceledException)
							{
								if (list.Count == 0)
								{
									break;
								}
								if (list.Count < 3)
								{
									YJKMessageBox.Information("选取的顶点数小于3，无法布置，请重新选取！！");
									continue;
								}
							}
							if (list.First<XYZ>().DistanceTo(list.Last<XYZ>()) < 0.001)
							{
								list.Remove(list.Last<XYZ>());
							}
							yxfloorPipeManager = new YXFloorPipeManager(this.floorPipeTools.DealYxPoints(list, this.selection), hydrawYXDrpgForm.drawYxFloorPipe);
							CurveArray curveArray = new CurveArray();
							for (int j = 0; j < list.Count; j++)
							{
								Curve curve;
								if (j == list.Count - 1)
								{
									curve = Line.CreateBound(list[j], list[0]);
								}
								else
								{
									curve = Line.CreateBound(list[j], list[j + 1]);
								}
								curveArray.Append(curve);
							}
							markPoint = YJKRevitTools.Centroid(curveArray);
						}
						subTransaction.Start();
						if (!yxfloorPipeManager.Draw())
						{
							YJKMessageBox.Information("选择的区域，可能由于尺寸原因，造成无法绘制，\n请重新选择绘制区域！");
							subTransaction.RollBack();
							continue;
						}
						yxfloorPipeManager.CreateCurve();
						floorPipeGroupData.PipesLength = yxfloorPipeManager.CalcTolLength();
						List<Element> list2 = new List<Element>();
						list2.AddRange(this.floorPipeTools.CreatModelLine(yxfloorPipeManager.allCurveIn, hydrawYXDrpgForm.drawYxFloorPipe.InType, ref floorPipeGroupData.PipeInId));
						list2.AddRange(this.floorPipeTools.CreatModelLine(yxfloorPipeManager.allCurveOut, hydrawYXDrpgForm.drawYxFloorPipe.OutType, ref floorPipeGroupData.PipeLastId));
						if (floorPipeGroupData.drawYxFloorPipeData.IsDouble == 0)
						{
							floorPipeGroupData.PipeLastId = list2.Last<Element>().Id;
						}
						this.document.Regenerate();
						ElementSet elementSet = new ElementSet();
						foreach (Element element2 in from elem in list2
						where elem != null
						select elem)
						{
							elementSet.Insert(element2);
						}
						Autodesk.Revit.DB.Group group = this.document.CreatYJKGroup(elementSet);
						this.floorPipeTools.SetElementES(group, floorPipeGroupData);
						if (hydrawYXDrpgForm.bMarkTag)
						{
							RectFloorPipe.MarkFloorPipes(this.document, markPoint, floorPipeGroupData.PipesLength, hydrawYXDrpgForm.drawYxFloorPipe.Dis * 304.8, QuadrantLocation.XPosition);
						}
						subTransaction.Commit();
						continue;
					}
					catch (Autodesk.Revit.Exceptions.OperationCanceledException)
					{
						if (subTransaction != null && (int)subTransaction.GetStatus() == 1)
						{
							subTransaction.Commit();
						}
					}
					catch (Exception ex)
					{
						ex.ToString();
						YJKMessageBox.Information("选择的绘制区域，边界处理不完善，无法绘制!\n");
						if (subTransaction != null && (int)subTransaction.GetStatus() == 1)
						{
							subTransaction.RollBack();
						}
						continue;
					}
					break;
				}
			}
		}

		private bool JustSetContantXyz(List<XYZ> points, XYZ point)
		{
			foreach (XYZ xyz in points)
			{
				if (point.DistanceTo(xyz) < 0.0001)
				{
					return true;
				}
			}
			return false;
		}

		private void DrawPipes(XYZ pt1, XYZ pt2, XYZ pt3, DrawFloorPipeData df, bool bMark = false)
		{
			FloorPipeGroupData floorPipeGroupData = new FloorPipeGroupData();
			DrpgDrawManager drpgDrawManager = new DrpgDrawManager(pt1, pt2, pt3, df);
			floorPipeGroupData.drawFloorPipeData = df;
			if (!drpgDrawManager.DispatchRegion())
			{
				YJKMessageBox.Information("当前选择的区域过小，无法绘制！");
				return;
			}
			drpgDrawManager.CreateCurves();
			floorPipeGroupData.PipesLength = drpgDrawManager.GetAllCurveLength();
			if (floorPipeGroupData.PipesLength > 120.0 && DialogResult.No == YJKMessageBox.Show("根据《辐射供暖供冷技术规程》JGJ 142-2012中3.5.5的规定，同\n一环路的加热管长度不宜超过120m。是否继续绘制？", MessageBoxButtons.YesNo))
			{
				return;
			}
			List<Element> list = new List<Element>();
			list.AddRange(this.floorPipeTools.CreatModelLine(drpgDrawManager.m_aryCurvesIn, df.InType, ref floorPipeGroupData.PipeInId));
			if (df.PipeStyle == FloorPipeStyle.STYLE_DANHUIZHUAN)
			{
				floorPipeGroupData.PipeLastId = this.LastLineId(list);
			}
			list.AddRange(this.floorPipeTools.CreatModelLine(drpgDrawManager.m_aryCurvesOut, df.OutType));
			this.document.Regenerate();
			ElementSet elementSet = new ElementSet();
			foreach (Element element in from elem in list
			where elem != null
			select elem)
			{
				elementSet.Insert(element);
			}
			Autodesk.Revit.DB.Group group = this.document.CreatYJKGroup(elementSet);
			this.floorPipeTools.SetElementES(group, floorPipeGroupData);
			if (bMark)
			{
				this.MarkTag(group, new XYZ[]
				{
					pt1,
					pt2,
					pt3
				}.ToList<XYZ>());
			}
		}

		private int DrawMore(List<XYZ> point, DrawFloorPipeData df)
		{
			int result = 1;
			FloorPipeGroupData floorPipeGroupData = new FloorPipeGroupData();
			DrpgDrawManager drpgDrawManager = new DrpgDrawManager(point[1], point[2], point[3], df);
			floorPipeGroupData.drawFloorPipeData = df;
			if (!drpgDrawManager.DispatchRegion())
			{
				return 1;
			}
			drpgDrawManager.CreateCurves();
			floorPipeGroupData.PipesLength = drpgDrawManager.GetAllCurveLength();
			if (floorPipeGroupData.PipesLength > 120.0 && DialogResult.Yes == YJKMessageBox.Show("房间内绘制一挂盘管，长度大于120m，\n是否划分区域绘制多挂？", MessageBoxButtons.YesNo))
			{
				result = (int)Math.Ceiling(floorPipeGroupData.PipesLength / 120.0);
			}
			return result;
		}

		private void DrawPipes(List<XYZ> point, DrawFloorPipeData df, bool bMark = false)
		{
			FloorPipeGroupData floorPipeGroupData = new FloorPipeGroupData();
			DrpgDrawManager drpgDrawManager = new DrpgDrawManager(point[1], point[2], point[3], df);
			floorPipeGroupData.drawFloorPipeData = df;
			if (!drpgDrawManager.DispatchRegion())
			{
				YJKMessageBox.Information("当前选中的房间，尺寸太小，无法绘制！");
				return;
			}
			drpgDrawManager.CreateCurves();
			floorPipeGroupData.PipesLength = drpgDrawManager.GetAllCurveLength();
			List<Element> list = new List<Element>();
			list.AddRange(this.floorPipeTools.CreatModelLine(drpgDrawManager.m_aryCurvesIn, df.InType, ref floorPipeGroupData.PipeInId));
			if (df.PipeStyle == FloorPipeStyle.STYLE_DANHUIZHUAN)
			{
				floorPipeGroupData.PipeLastId = this.LastLineId(list);
			}
			list.AddRange(this.floorPipeTools.CreatModelLine(drpgDrawManager.m_aryCurvesOut, df.OutType));
			this.document.Regenerate();
			ElementSet elementSet = new ElementSet();
			foreach (Element element in from elem in list
			where elem != null
			select elem)
			{
				elementSet.Insert(element);
			}
			Autodesk.Revit.DB.Group group = this.document.CreatYJKGroup(elementSet);
			this.floorPipeTools.SetElementES(group, floorPipeGroupData);
			if (bMark)
			{
				this.MarkTag(group, point);
			}
		}

		private ElementId LastLineId(List<Element> elems)
		{
			for (int i = elems.Count - 1; i >= 0; i--)
			{
				if (elems[i] is ModelLine)
				{
					return elems[i].Id;
				}
			}
			return null;
		}

		private void MarkTag(Autodesk.Revit.DB.Group group, List<XYZ> pointList)
		{
			XYZ xyz = pointList[0];
			XYZ xyz2 = pointList[1];
			XYZ xyz3 = pointList[2];
			XYZ markPoint = xyz.Add(xyz3) / 2.0;
			FloorPipeGroupData elementES = this.floorPipeTools.GetElementES(group);
			double floorPipeDistance = this.floorPipeTools.GetFloorPipeDistance(elementES);
			double pipesLength = elementES.PipesLength;
			RectFloorPipe.MarkFloorPipes(this.document, markPoint, pipesLength, floorPipeDistance, QuadrantLocation.XPosition);
		}

		public static void MarkFloorPipes(Autodesk.Revit.DB.Document doc, XYZ markPoint, double length, double distance, QuadrantLocation pointQuadrant)
		{
			List<Element> list = new List<Element>();
			XYZ upDirection = doc.ActiveView.UpDirection;
			XYZ rightDirection = doc.ActiveView.RightDirection;
			string strTextNode = "长度:" + Math.Round(length, 1) + "m";
			string strTextNode2 = "间距:" + Math.Round(distance) + "mm";
			SubTransaction subTransaction = new SubTransaction(doc);
			YJKRotateFamilyInstance hyrotateFamilyInstance = new YJKRotateFamilyInstance();
			try
			{
				subTransaction.Start();
				TextNoteType textNoteType = FloorPipeMarkingTool.ChangeTextNodeType(doc);
				TextNote textNote = UnifiedModified.HYCreatTextNote(doc, strTextNode, markPoint, textNoteType);
				doc.Regenerate();
				double num = (double)doc.ActiveView.Scale;
				double num2 = textNote.Height * num;
				double num3 = UnifiedModified.GetTextNoteWidth(doc, textNote) * 1.05;
				TextNote textNote2 = UnifiedModified.HYCreatTextNote(doc, strTextNode2, markPoint, textNoteType);
				num3 = ((UnifiedModified.GetTextNoteWidth(doc, textNote2) * 1.05 > num3) ? (UnifiedModified.GetTextNoteWidth(doc, textNote2) * 1.05) : num3);
				if (int.Parse(RevitVersion.Version) <= 2015)
				{
					num3 *= 100.0;
				}
				list.Add(textNote);
				list.Add(textNote2);
				subTransaction.Commit();
				List<XYZ> drawRectanglePoints = FloorPipeMarkingTool.GetDrawRectanglePoints(markPoint, pointQuadrant, doc, num3, 2.0 * num2);
				if (RevitVersion.Version == "2015")
				{
					markPoint = markPoint.Add(num2 / 2.0 * doc.ActiveView.UpDirection);
				}
				XYZ moveVector = drawRectanglePoints[0].Subtract(markPoint);
				hyrotateFamilyInstance.MoveElement(moveVector, textNote);
				XYZ moveVector2 = (drawRectanglePoints[0].Add(drawRectanglePoints[1]) / 2.0).Subtract(markPoint);
				hyrotateFamilyInstance.MoveElement(moveVector2, textNote2);
				FloorPipeMarkingTool.CreatRectangleLines(doc, drawRectanglePoints, ref list);
				doc.Regenerate();
				FloorPipeMarkingTool.CreateGroup(list, doc);
			}
			catch (Exception ex)
			{
				string message = ex.Message;
				if (subTransaction != null && (int)subTransaction.GetStatus() == 1)
				{
					subTransaction.RollBack();
				}
			}
		}

		private void DrawMarksToTheFloorPipes(Autodesk.Revit.DB.Document doc, XYZ ep, double length, double distance, XYZ vecBase, XYZ vecUp)
		{
			List<Element> list = new List<Element>();
			double num = 3.2808398950131235;
			XYZ xyz = ep + vecUp * num;
			XYZ xyz2 = xyz + vecBase * 2.0 * num;
			XYZ xyz3 = ep + vecBase * 2.0 * num;
			list.Add(YJKRevitTools.DrawDetailLine(doc, ep, xyz));
			list.Add(YJKRevitTools.DrawDetailLine(doc, xyz, xyz2));
			list.Add(YJKRevitTools.DrawDetailLine(doc, xyz2, xyz3));
			list.Add(YJKRevitTools.DrawDetailLine(doc, xyz3, ep));
			XYZ origin = ep + vecBase * num / 5.0 + vecUp * 820.0 / 304.8;
			XYZ origin2 = ep + vecBase * num / 5.0 + vecUp * 500.0 / 304.8;
			string strText = "长度:" + Math.Round(length, 1) + "m";
			string strText2 = "间距:" + Math.Round(distance) + "mm";
			TextNote textNode = doc.GetTextNode(doc.ActiveView, origin, vecBase, vecUp, 0.00984251968503937, (Autodesk.Revit.DB.TextAlignFlags)64, strText, 15.0);
			textNode.TextNoteType = FloorPipeMarkingTool.ChangeTextNodeType(textNode);
			list.Add(textNode);
			TextNote textNode2 = doc.GetTextNode(doc.ActiveView, origin2, vecBase, vecUp, 0.00984251968503937, (Autodesk.Revit.DB.TextAlignFlags)64, strText2, 15.0);
			textNode2.TextNoteType = FloorPipeMarkingTool.ChangeTextNodeType(textNode2);
			list.Add(textNode2);
			doc.Regenerate();
			FloorPipeMarkingTool.CreateGroup(list, doc);
		}

		private Document document;

		private Selection selection;

		private FloorPipeTools floorPipeTools;

		private UIDocument uiDocument;

		private Element room;

		private bool bLayOnce;

		private Dictionary<string, string> dic;
	}
}
